﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using TinyForum.DataObjects;
using TinyForum.Application;
using TinyForum.Infrastructure;
using Apworks.Repositories;
using Apworks;

namespace TinyForum.Services
{
    public class TinyForumService : ITinyForumService
    {
        #region Private Fields
        private readonly IAccountApplication accountApplication;
        private readonly ITopicApplication topicApplication;
        private readonly ISiteApplication siteApplication;
        private readonly IPostApplication postApplication;
        #endregion

        #region Ctor
        public TinyForumService()
        {
            this.accountApplication = CommonUtils.ObjectContainer.GetService<IAccountApplication>();
            this.topicApplication = CommonUtils.ObjectContainer.GetService<ITopicApplication>();
            this.siteApplication = CommonUtils.ObjectContainer.GetService<ISiteApplication>();
            this.postApplication = CommonUtils.ObjectContainer.GetService<IPostApplication>();
        }
        #endregion

        #region IAccountApplication Members

        public long Register(AccountDataObject accountDataObject)
        {
            try
            {
                return this.accountApplication.Register(accountDataObject);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public bool AccountExists(string userName)
        {
            try
            {
                return this.accountApplication.AccountExists(userName);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public bool Authenticate(string userName, string password)
        {
            try
            {
                return accountApplication.Authenticate(userName, password);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public void GrantAdminPrivilege(string userName)
        {
            try
            {
                accountApplication.GrantAdminPrivilege(userName);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public IEnumerable<AccountDataObject> GetAccountsByUserName(string userName)
        {
            try
            {
                return accountApplication.GetAccountsByUserName(userName);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application), 
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks), 
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System), 
                    new FaultReason(ex.Message));
            }
        }

        public IEnumerable<AccountDataObject> GetAccountsByEmail(string email)
        {
            try
            {
                return accountApplication.GetAccountsByEmail(email);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public AccountDataObject GetAccount(long id)
        {
            try
            {
                return accountApplication.GetAccount(id);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application), 
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks), 
                    new FaultReason(apworksException.Message));
            }
            catch(Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System), 
                    new FaultReason(ex.Message));
            }
        }
        
        public IEnumerable<AccountDataObject> GetAllAccounts()
        {
            try
            {
                return accountApplication.GetAllAccounts();
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public string GetPassword(string userName, string passwordAnswer)
        {
            try
            {
                return accountApplication.GetPassword(userName, passwordAnswer);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            try
            {
                return accountApplication.ChangePassword(userName, oldPassword, newPassword);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public bool ChangePasswordQuestionAndAnswer(string userName, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            try
            {
                return accountApplication.ChangePasswordQuestionAndAnswer(userName, password, newPasswordQuestion, newPasswordAnswer);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public string ResetPassword(string userName, string answer)
        {
            try
            {
                return accountApplication.ResetPassword(userName, answer);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public void Lock(string userName)
        {
            try
            {
                accountApplication.Lock(userName);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public void Unlock(string userName)
        {
            try
            {
                accountApplication.Unlock(userName);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public void UpdateInformation(string userName, string displayName, string email)
        {
            try
            {
                accountApplication.UpdateInformation(userName, displayName, email);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }
        #endregion

        #region ITopicApplication Members

        public long CreateTopic(string name, string description)
        {
            try
            {
                return topicApplication.CreateTopic(name, description);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public TopicDataObject GetTopic(long id)
        {
            try
            {
                return topicApplication.GetTopic(id);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public TopicDetailDataObject GetTopicDetail(long topicId)
        {
            try
            {
                return topicApplication.GetTopicDetail(topicId);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public IEnumerable<TopicDetailDataObject> GetTopicDetails()
        {
            try
            {
                return topicApplication.GetTopicDetails();
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public IEnumerable<PostDataObject> GetPosts(long topicId, PostSortDataObject postSort, SortOrderDataObject sortOrder)
        {
            try
            {
                return topicApplication.GetPosts(topicId, postSort, sortOrder);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        #endregion

        #region ISiteApplication Members

        public SettingDataObject GetSiteSettings()
        {
            try
            {
                return siteApplication.GetSiteSettings();
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        public void SaveSiteSettings(SettingDataObject setting)
        {
            try
            {
                siteApplication.SaveSiteSettings(setting);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        #endregion

        #region IPostApplication Members

        public PostDetailDataObject GetPostDetail(long postId)
        {
            try
            {
                return postApplication.GetPostDetail(postId);
            }
            catch (DomainException domainException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(domainException, FaultSourceType.Application),
                    new FaultReason(domainException.Message));
            }
            catch (ApworksException apworksException)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(apworksException, FaultSourceType.Apworks),
                    new FaultReason(apworksException.Message));
            }
            catch (Exception ex)
            {
                throw new FaultException<ApplicationFaultDetail>(new ApplicationFaultDetail(ex, FaultSourceType.System),
                    new FaultReason(ex.Message));
            }
        }

        #endregion
    }
}
